home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / BSP Tree 1.2 / Sources / Graphics / source / bspnode_3d.cp < prev    next >
Encoding:
Text File  |  1995-03-26  |  14.1 KB  |  204 lines  |  [TEXT/MMCC]

  1. //------------------------------------------------------------------------------
  2. //    File:                    bspnode.cp
  3. //    Date:                    9/25/94
  4. //    Author:                Bretton Wade
  5. //
  6. //    Description:    this file contains the methods for a bsp tree node
  7. //
  8. //------------------------------------------------------------------------------
  9.  
  10. #include "utility.h"
  11. #include "bspnode_3d.h"
  12. #include "iterator_3d.h"
  13.  
  14. //------------------------------------------------------------------------------
  15. //    constructor
  16. //------------------------------------------------------------------------------
  17. bspnode::bspnode (polyptr &poly)                                                                                                //    normal constructor
  18. {                                                                                                                                                                //    begin
  19.     plane = poly->Plane ();                                                                                                                //    copy the plane_3d equation
  20.     on->AddToList (poly);                                                                                                                    //    install the polygon in the 'on' list
  21. }                                                                                                                                                                //    end
  22.  
  23. //------------------------------------------------------------------------------
  24. //    destructor
  25. //------------------------------------------------------------------------------
  26. bspnode::~bspnode (void)                                                                                                                //    destructor
  27. {                                                                                                                                                                //    begin
  28. }                                                                                                                                                                //    end
  29.  
  30. //------------------------------------------------------------------------------
  31. //    insert a list of faces
  32. //------------------------------------------------------------------------------
  33. void    bspnode::Insert (listptr list, hclass keep)                                                                //    insert a list of polygons into the tree
  34. {                                                                                                                                                                //    begin
  35.     listptr    inside, outside;                                                                                                            //    lists corresponding to partitions
  36.     polyptr        poly, inp, outp;                                                                                                        //    source polygon and partitions
  37.     for (poly = list->Pop (); poly (); poly = list->Pop ())                                                //    loop over the polygons in the list one ata a time
  38.     {                                                                                                                                                            //    begin
  39.         hclass    sgn = Split (poly, plane, inp, outp);                                                                //    clip the polygon by the partitioning plane_3d
  40.         if (sgn == ON)                                                                                                                            //    if the source polygon lies within the partitioning plane_3d
  41.             on->AddToList (poly);                                                                                                            //    insert it into the coincident faces list
  42.         else                                                                                                                                                //    otherwise
  43.         {                                                                                                                                                        //    begin
  44.             if ((sgn == IN) || (sgn == SPANNING))                                                                            //    if some part of the result is inside
  45.                 inside->AddToList (inp);                                                                                                //    send it through the inside children
  46.             if ((sgn == OUT) || (sgn == SPANNING))                                                                        //    if some part of the result is outside
  47.                 outside->AddToList (outp);                                                                                            //    send it through the outside children
  48.         }                                                                                                                                                        //    end
  49.     }                                                                                                                                                            //    end
  50.     if (!inside->Empty ())                                                                                                                //    if the inside list is not empty
  51.         in.Insert (inside, keep, IN);                                                                                                //    insert the inside list into the inside children
  52.     if (!outside->Empty ())                                                                                                                //    if the outside list is not empty
  53.         out.Insert (outside, keep, OUT);                                                                                        //    insert the outside list into the outside children
  54. }                                                                                                                                                                //    end
  55.  
  56. //------------------------------------------------------------------------------
  57. //    push a single face through the tree
  58. //------------------------------------------------------------------------------
  59. void    bspnode::Push (polyptr poly, listptr result, hclass keep)                                    //    push a list of polygons through the tree
  60. {                                                                                                                                                                //    begin
  61.     listptr    inside, outside;                                                                                                            //    lists corresponding to partitions
  62.     polyptr    inp, outp;                                                                                                                        //    source polygon and its partitions
  63.     hclass    sgn = Split (poly, plane, inp, outp);                                                                    //    clip the polygon by the partitioning plane_3d
  64.     if (sgn == ON)                                                                                                                                //    if the source polygon lies within the partitioning plane_3d
  65.         result->AddToList (poly);                                                                                                        //    insert it into the result list
  66.     else                                                                                                                                                    //    otherwise
  67.     {                                                                                                                                                            //    begin
  68.         if ((sgn == IN) || (sgn == SPANNING))                                                                                //    if some part of the result is inside
  69.             in.Push (inp, result, keep, IN);                                                                                    //    push it through the in node
  70.         if ((sgn == OUT) || (sgn == SPANNING))                                                                            //    if some part of the result is outside
  71.             out.Push (outp, result, keep, OUT);                                                                                //    push it through the out node
  72.     }                                                                                                                                                            //    end
  73. }                                                                                                                                                                //    end
  74.  
  75. //------------------------------------------------------------------------------
  76. //    push a list of faces through the tree
  77. //------------------------------------------------------------------------------
  78. void    bspnode::Push (listptr list, listptr result, hclass keep)                                    //    push a list of polygons through the tree
  79. {                                                                                                                                                                //    begin
  80.     listptr    inside, outside;                                                                                                            //    lists corresponding to partitions
  81.     polyptr        poly, inp, outp;                                                                                                        //    source polygon and its partitions
  82.     for (poly = list->Pop (); poly (); poly = list->Pop ())                                                //    loop through all of the polygons in the list
  83.     {                                                                                                                                                            //    begin
  84.         hclass    sgn = Split (poly, plane, inp, outp);                                                                //    clip the polygon by the partitioning plane_3d
  85.         if (sgn == ON)                                                                                                                            //    if the source polygon lies within the partitioning plane_3d
  86.             result->AddToList (poly);                                                                                                    //    insert it into the result list
  87.         else                                                                                                                                                //    otherwise
  88.         {                                                                                                                                                        //    begin
  89.             if ((sgn == IN) || (sgn == SPANNING))                                                                            //    if some part of the result is inside
  90.                 inside->AddToList (inp);                                                                                                //    send it through the inside children
  91.             if ((sgn == OUT) || (sgn == SPANNING))                                                                        //    if some part of the result is outside
  92.                 outside->AddToList (outp);                                                                                            //    send it through the outside children
  93.         }                                                                                                                                                        //    end
  94.     }                                                                                                                                                            //    end
  95.     if (!inside->Empty ())                                                                                                                //    if the inside list is not empty
  96.         in.Push (inside, result, keep, IN);                                                                                    //    push the inside list through the inside children
  97.     if (!outside->Empty ())                                                                                                                //    if the outside list is not empty
  98.         out.Push (outside, result, keep, OUT);                                                                            //    push the outside list through the outside children
  99. }                                                                                                                                                                //    end
  100.  
  101. //------------------------------------------------------------------------------
  102. //    reduce to boundary polygons
  103. //------------------------------------------------------------------------------
  104. void    bspnode::Reduce (void)                                                                                                        //    reduce the tree to only boundary polygons
  105. {                                                                                                                                                                //    begin
  106.     listptr    results, boundary;                                                                                                        //    results lists
  107.     for (polyptr poly = on->Pop (); poly (); poly = on->Pop ())                                        //    loop through all of the polygons in the list
  108.     {                                                                                                                                                            //    begin
  109.         if (abs (poly->Plane ()[W] + plane[W]) > EPSILON)                                                        //    if the plane_3d is facing the same way as the polygon
  110.         {                                                                                                                                                        //    begin
  111.             in.Push (poly, results, IN, IN);                                                                                    //    push the polygon down and keep in bits
  112.             out.Push (results, boundary, OUT, OUT);                                                                        //    push the results down and keep the out bits
  113.         }                                                                                                                                                        //    end
  114.         else                                                                                                                                                //    otherwise, the plane_3d and polygon are facing opposite directions
  115.         {                                                                                                                                                        //    begin
  116.             out.Push (poly, results, OUT, OUT);                                                                                //    push the polygon down and keep the out bits
  117.             in.Push (results, boundary, IN, IN);                                                                            //    push the results down and keep in bits
  118.         }                                                                                                                                                        //    end
  119.     }                                                                                                                                                            //    end
  120.     on = boundary;                                                                                                                                //    assign the new coincident faces list
  121.     in.Reduce ();                                                                                                                                    //    tell the in child to compute its boundaries
  122.     out.Reduce ();                                                                                                                                //    tell the out children to compute its boundaries
  123. }                                                                                                                                                                //    end
  124.  
  125. //------------------------------------------------------------------------------
  126. //    draw
  127. //------------------------------------------------------------------------------
  128. void    bspnode::Draw (const point_3d &eye) const                                                                    //    draw the tree
  129. {                                                                                                                                                                //    begin
  130.     real    sgn = eye | plane;                                                                                                            //    compute the distance from the eye to the plane_3d
  131.     if (sgn < R(0.0))                                                                                                                            //    if the eye is on the negative side of the plane_3d
  132.     {                                                                                                                                                            //    begin
  133.         out.Draw (eye);                                                                                                                            //    draw the positive side children
  134.         on->Draw ();                                                                                                                                //    draw the polygons coincident with the dividing plane_3d
  135.         in.Draw (eye);                                                                                                                            //    draw the negative side children
  136.     }                                                                                                                                                            //    end
  137.     else                                                                                                                                                    //    otherwise
  138.     {                                                                                                                                                            //    begin
  139.         in.Draw (eye);                                                                                                                            //    draw the negative side children
  140.         on->Draw ();                                                                                                                                //    draw the polygons coincident with the dividing plane_3d
  141.         out.Draw (eye);                                                                                                                            //    draw the positive side children
  142.     }                                                                                                                                                            //    end
  143. }                                                                                                                                                                //    end
  144.  
  145. //------------------------------------------------------------------------------
  146. //    trace a ray through the node
  147. //------------------------------------------------------------------------------
  148. bool    bspnode::RayIntersection (const ray &r, polyptr &poly_hit, point_3d &ipt) const    //    compute the polygon intersected by a ray
  149. {                                                                                                                                                                //    begin
  150.     real    dist = r.Origin () | plane,                                                                                            //    compute the distance from the ray origin to the plane_3d
  151.                 costheta = r.Direction () | plane;                                                                            //    compute the cosine of the angle between the ray direction and the plane_3d normal
  152.     if (dist > EPSILON)                                                                                                                        //    if the ray originates on the positive side of the plane_3d
  153.     {                                                                                                                                                            //    begin
  154.         if (out.RayIntersection (r, poly_hit, ipt)) return TRUE;                                        //    trace the ray into the positive child
  155.         if (costheta < -EPSILON)                                                                                                        //    if the ray direction is headed into the plane_3d
  156.         {                                                                                                                                                        //    begin
  157.             if (PlaneSearch (r, poly_hit, ipt)) return TRUE;                                                    //    check the intersection with the coincident list
  158.             return in.RayIntersection (r, poly_hit, ipt);                                                            //    trace the ray through the negative child
  159.         }                                                                                                                                                        //    end
  160.     }                                                                                                                                                            //    end
  161.     else if (dist < -EPSILON)                                                                                                            //    otherwise, if the ray originates on the negative side of the plane_3d
  162.     {                                                                                                                                                            //    begin
  163.         if (in.RayIntersection (r, poly_hit, ipt)) return TRUE;                                            //    trace the ray through the negative child
  164.         if (costheta > EPSILON)                                                                                                            //    if the ray direction is headed into the plane_3d
  165.         {                                                                                                                                                        //    begin
  166.             if (PlaneSearch (r, poly_hit, ipt)) return TRUE;                                                    //    check the intersection with the coincident list
  167.             return out.RayIntersection (r, poly_hit, ipt);                                                        //    trace the ray into the positive child
  168.         }                                                                                                                                                        //    end
  169.     }                                                                                                                                                            //    end
  170.     else                                                                                                                                                    //    otehrwise, the ray originbates on the plane_3d
  171.     {                                                                                                                                                            //    begin
  172.         if (costheta < -EPSILON)                                                                                                        //    if the ray is headed in
  173.             return in.RayIntersection (r, poly_hit, ipt);                                                            //    trace the ray through the negative child
  174.         else if (costheta > EPSILON)                                                                                                //    otherwise, if the ray is headed out
  175.             return out.RayIntersection (r, poly_hit, ipt);                                                        //    trace the ray through the positive child
  176.     }                                                                                                                                                            //    end
  177.     return FALSE;                                                                                                                                    //    the ray did not intersect anything in this tree
  178. }                                                                                                                                                                //    end
  179.  
  180. //------------------------------------------------------------------------------
  181. //    find a ray intersection with the coincident polygon list
  182. //------------------------------------------------------------------------------
  183. bool    bspnode::PlaneSearch (const ray &r, polyptr &poly_hit, point_3d &ipt) const    //    find the intersection of a ray and the plane_3d list
  184. {                                                                                                                                                                //    begin
  185.     real    dist = plane.RayIntersection (r);                                                                                //    compute the distance along the ray to the plane_3d
  186.     if (dist > R(0.0))                                                                                                                        //    if it is positive
  187.     {                                                                                                                                                            //    begin
  188.         ipt = r.IntersectionPoint (dist);                                                                                        //    compute the intersection point_3d
  189.         if (on->BoundingBox ().Contains (ipt))                                                                            //    check to see if it is in the bounding box for the list
  190.         {                                                                                                                                                        //    begin
  191.             iterator    entry (on);                                                                                                            //    list iterator
  192.             for (polyptr poly = entry (); poly (); poly = entry ())                                        //    do for all the entries in th elist
  193.                 if (poly->Contains (ipt))                                                                                                //    if the point_3d is inside the polygon
  194.                 {                                                                                                                                                //    begin
  195.                     poly_hit = poly;                                                                                                            //    set the hit polygon
  196.                     return TRUE;                                                                                                                    //    return the success
  197.                 }                                                                                                                                                //    end
  198.         }                                                                                                                                                        //    end
  199.     }                                                                                                                                                            //    end
  200.     return FALSE;                                                                                                                                    //    no intersection, return FALSE
  201. }                                                                                                                                                                //    end
  202.  
  203. //------------------------------------------------------------------------------
  204.